第22章 位运算
位运算是指对二进制数的各个位进行操作的运算,它直接作用于数据的二进制位,具有运算速度快、效率高的特点,在计算机底层编程、数据压缩、加密算法等领域有着广泛的应用。
22.1 位运算的基本概念
位运算的操作对象是整数的二进制表示形式,这里的整数包括signed(有符号)和unsigned(无符号)类型。在进行位运算时,忽略整数的符号位(对于有符号数),仅对各个二进制位进行逻辑或算术操作。
例如,对于整数5(二进制为00000101)和3(二进制为00000011),位运算将直接对这两个二进制数的每一位进行操作。
22.2 常用的位运算符
22.2.1 按位与(&)
运算规则:两个二进制位都为1时,结果位为1;否则为0。 示例: 计算过程:逐位进行与运算,第1位 ,其余位运算结果全为0。
应用:
- 清零:
a & 0,所有位置0; - 截取指定位:
a & 0x0F取出低4位。
22.2.2 按位或(|)
运算规则:两个二进制位至少有一个为1,结果位为1;否则为0。 示例:
应用:置位,将指定二进制位设为1,如a | (1 << 3)把第3位改为1。
22.2.3 按位异或(^)
运算规则:两位不同则为1,相同则为0。 示例:
应用:
- 翻转掩码对应二进制位:
a ^ 0x0F翻转低4位; - 不借助临时变量交换两个整数:
a = a ^ b;
b = a ^ b;
a = a ^ b;
22.2.4 按位取反(~)
运算规则:所有二进制位0变1、1变0。
示例:~5 在32位系统结果为0xFFFFFFFA,数学公式:~a = -a - 1。
应用:生成全1掩码。
22.2.5 左移
规则:二进制整体左移N位,高位丢弃,低位补0。 示例: 特性:正数/无符号数左移N位等价乘以(无溢出前提下)。
22.2.6 右移
分两种类型:
- 无符号
unsigned:逻辑右移,低位丢弃,高位补0; - 有符号
signed:算术右移,低位丢弃,高位补符号位(正数补0,负数补1)。 示例: 无符号; 8位有符号; 特性:正数/无符号右移N位等价除以(向下取整)。
22.3 异或交换变量
#include <stdio.h>
int main(){
int a=5,b=10;
printf("交换前:a=%d,b=%d\n",a,b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("交换后:a=%d,b=%d\n",a,b);
return 0;
}
注意:两个变量不能是同一块内存,否则会全部置0。
22.4 位运算符优先级(从高到低)
~ > << >> > & > ^ > |
复杂表达式建议括号明确运算顺序,避免歧义。
示例:
int a=5,b=3;
int c = a & b | 1; // 先算&
int d = a & (b | 1);// 先算|
22.5 位运算应用场景
- 嵌入式硬件寄存器位控制;
- 图像RGB通道提取;
- 高效判断奇偶:
(a & 1) == 1; - 快速求2的幂:
1 << n; - 加密、压缩底层二进制处理。
22.6 使用注意事项
- 有符号数右移会补符号位,逻辑操作优先用
unsigned; - 左移溢出结果未定义;
- 位运算可读性差,必须加注释;
- 32/64位系统int长度不同,跨平台注意位数差异。